package com.functest.orm

import com.google.common.collect.Sets
import com.functest.framework.Assertions
import com.functest.framework.BaseFunctionalTest
import org.testng.annotations.DataProvider
import org.testng.annotations.Optional
import org.testng.annotations.Test

/**
 * Created with IntelliJ IDEA.
 * User: KovalevAS
 * Date: 28.06.13
 * Time: 16:15
 * To change this template use File | Settings | File Templates.
 */
class ConditionOpTest extends BaseFunctionalTest {
    private final Set ACCEPT_STRINGS_RIGHT = ConditionOp.values() - [ConditionOp.BTEQ, ConditionOp.BTNEQ, ConditionOp.BTANY, ConditionOp.IN, ConditionOp.NOT_IN]
    private final Set ACCEPT_STRINGS_LEFT = ConditionOp.values() - [ConditionOp.BTEQ, ConditionOp.BTNEQ, ConditionOp.BTANY]
    private final Set ACCEPT_NUMBERS_RIGHT = ConditionOp.values() - [ConditionOp.LIKE, ConditionOp.NOT_LIKE, ConditionOp.IN, ConditionOp.NOT_IN]
    private final Set ACCEPT_NUMBERS_LEFT = ConditionOp.values() - [ConditionOp.LIKE, ConditionOp.NOT_LIKE]
    private final Set ACCEPT_NULLS_LEFT = ConditionOp.values()
    private final Set ACCEPT_COLLECTIONS_RIGHT_SQL = [ConditionOp.IN, ConditionOp.NOT_IN]
    private final Set ACCEPT_COLLECTIONS_RIGHT_NON_SQL = ConditionOp.values() - [ConditionOp.LIKE, ConditionOp.NOT_LIKE, ConditionOp.BTEQ, ConditionOp.BTNEQ, ConditionOp.BTANY]
    private final Set ACCEPT_FIELDREFS_RIGHT = ConditionOp.values() - [ConditionOp.IN, ConditionOp.NOT_IN] // Applicable to BUILD_SQL only
    private final Set ACCEPT_NULLS_RIGHT_SQL = [ConditionOp.IS_NULL, ConditionOp.IS_NOT_NULL] as Set
    private final Set ACCEPT_NULLS_RIGHT_NONSQL = [ConditionOp.IS_NOT_NULL, ConditionOp.IS_NULL, ConditionOp.EQ, ConditionOp.NEQ] as Set
    private final Set CLASS_CAST_OPS = [ConditionOp.EQ, ConditionOp.NEQ, ConditionOp.LT, ConditionOp.GT, ConditionOp.LTE, ConditionOp.GTE, ConditionOp.LIKE, ConditionOp.NOT_LIKE]

    /** BuildSQL tests **/

    @Test
    void ConditionOp_buildSql_positive_Test() {
        def field = 'firstName'
        def mapper = TestData.student_table_full_mapper
        def value = 'value'
        FieldReference fe = new FieldReference(mapper, field)

        asStep('EQ .. LTE') {
            for (co in ConditionOp.EQ..ConditionOp.LTE) {
                assert co.buildSql(value) == co.sqlExpression.plus(" $value ")
                assert co.buildSql(fe) == co.sqlExpression.plus(mapper.getFqSourceName(field))
            }
        }

        asStep('LIKE, NOT_LIKE') {
            [ConditionOp.LIKE, ConditionOp.NOT_LIKE].each
                    {
                        assert it.buildSql(value) == it.sqlExpression.plus(" $value ")
                        assert it.buildSql(fe) == it.sqlExpression.plus(mapper.getFqSourceName(field))
                    }
        }

        asStep('IN, NOT_IN') {
            def v = [7, 8]
            [ConditionOp.IN, ConditionOp.NOT_IN].each
                    {
                        assert it.buildSql(v) == SqlMappingUtil.buildInClause(it, v as List)
                        if (it == ConditionOp.IN) {
                            assert it.buildSql([]) == ' IN (NULL /* IN(EMPTY_SET) */)  '
                        } else {
                            assert it.buildSql([]) == ' + NULL IS NULL /* NOT_IN(EMPTY_SET) */  '
                        }
                    }


        }

        asStep('IS_NULL, IS_NOT_NULL') {
            //TODO:
            [ConditionOp.IS_NULL, ConditionOp.IS_NOT_NULL].each
                    {

                        assert it.buildSql(value) == " $it ".replace('_', ' ')
                        assert it.buildSql(fe) == " $it ".replace('_', ' ')
                    }
        }

        asStep('BTEQ, BTNEQ, BTANY') {
            def v = 1
            assert ConditionOp.BTEQ.buildSql(v) == " & $v <> 0 "
            assert ConditionOp.BTNEQ.buildSql(v) == " & ${v} = 0 "
            assert ConditionOp.BTANY.buildSql(v) == " | ${v} <> 0 "
        }
    }


    @DataProvider
    Object[][] dpBuildSqlOperandTypes() {
        [
                ['STRING', ACCEPT_STRINGS_RIGHT, ['', 'QWERTY', "${System.currentTimeMillis()}", 'ФЫВА']]
                , ['NUMBERS', ACCEPT_NUMBERS_RIGHT, [0, Long.MAX_VALUE, Long.MIN_VALUE]]
                , ['NULLS', ACCEPT_NULLS_RIGHT_SQL, [null]]
                , ['COLLECTIONS', ACCEPT_COLLECTIONS_RIGHT_SQL, [[], ['1', '2', '3'], [1, 2, 3], [null, '2', '3']]]
                , ['FIELDREFS', ACCEPT_FIELDREFS_RIGHT, [new FieldReference(new Mapper(new MapperFields().build{field('id')}),'id')]]
        ]
    }

    @Test(dataProvider = 'dpBuildSqlOperandTypes')
    void conditionOp_buildSql_supportedOperandsForOperations_positive(String desc, Collection<ConditionOp> ops, Collection casez) {
        assert desc
        asTest {
            (ConditionOp.values() - ops).each { ConditionOp op ->
                casez.each { def caze ->
                    asStep("${op}.buildSql(${caze})") {
                        Exception ex = null
                        try {
                            def res = op.buildSql(caze)
                            logger.warn "result is:$res"
                        } catch (IllegalArgumentException iae) {
                            ex = iae
                        }
                        Assertions.weakAssertTrue("Illegal argument exception caught (but ${ex ?: 'nothing'} caught)", ex instanceof IllegalArgumentException)
                    }

                }
            }
        }
    }

    @Test(dataProvider = 'dpBuildSqlOperandTypes')
    void conditionOp_buildSql_supportedOperandsForOperations_negative(String desc, Collection<ConditionOp> ops, Collection casez) {
        assert desc
        asTest {
            ops.each { ConditionOp op ->
                casez.each { def caze ->
                    asStep("${op}.buildSql(${caze})") {
                        try {
                            op.buildSql(caze)
                        } catch (Exception e) {
                            Assertions.weakAssertTrue("No exception (but $e caught)", false)
                        }
                    }

                }
            }
        }
    }


    @DataProvider
    Object[][] dpApplyOperandTypes() {
        [
                ['LEFT: NUMBER, RIGHT: NUMBER, SQL', Sets.intersection(ACCEPT_NUMBERS_LEFT, ACCEPT_NUMBERS_RIGHT), [3, Long.MAX_VALUE], true]
                , ['LEFT: NUMBER, RIGHT: NUMBER, NONSQL', Sets.intersection(ACCEPT_NUMBERS_LEFT, ACCEPT_NUMBERS_RIGHT), [3, Long.MAX_VALUE], false]
                , ['LEFT: NUMBER, RIGHT: STRING, SQL', Sets.intersection(ACCEPT_NUMBERS_LEFT, ACCEPT_STRINGS_RIGHT), [3, '24'], true]
                , ['LEFT: NUMBER, RIGHT: STRING, NONSQL', Sets.intersection(ACCEPT_NUMBERS_LEFT, ACCEPT_STRINGS_RIGHT), [3, '24'], false]
                , ['LEFT: NUMBER, RIGHT: NULL, SQL', Sets.intersection(ACCEPT_NUMBERS_LEFT, ACCEPT_NULLS_RIGHT_SQL), [3, null], true]
                , ['LEFT: NUMBER, RIGHT: NULL, NONSQL', Sets.intersection(ACCEPT_NUMBERS_LEFT, ACCEPT_NULLS_RIGHT_NONSQL), [3, null], false]
                , ['LEFT: NUMBER, RIGHT: COLLECTION, SQL', Sets.intersection(ACCEPT_NULLS_LEFT, ACCEPT_COLLECTIONS_RIGHT_SQL), [Long.MAX_VALUE, ['a']], true]
                , ['LEFT: NUMBER, RIGHT: COLLECTION, NONSQL', Sets.intersection(ACCEPT_NULLS_LEFT, ACCEPT_COLLECTIONS_RIGHT_NON_SQL), [Integer.MIN_VALUE, [3, 4]], false]
                , ['LEFT: STRING, RIGHT: NUMBER, SQL', Sets.intersection(ACCEPT_STRINGS_LEFT, ACCEPT_NUMBERS_RIGHT), ['24', 3], true]
                , ['LEFT: STRING, RIGHT: NUMBER, NONSQL', Sets.intersection(ACCEPT_STRINGS_LEFT, ACCEPT_NUMBERS_RIGHT), ['24', 3], false]
                , ['LEFT: STRING, RIGHT: STRING, SQL', Sets.intersection(ACCEPT_STRINGS_LEFT, ACCEPT_STRINGS_RIGHT), ['234', '2%4'], true]
                , ['LEFT: STRING, RIGHT: STRING, NONSQL', Sets.intersection(ACCEPT_STRINGS_LEFT, ACCEPT_STRINGS_RIGHT), ['234', '2%4'], false]
                , ['LEFT: STRING, RIGHT: NULL, SQL', Sets.intersection(ACCEPT_STRINGS_LEFT, ACCEPT_NULLS_RIGHT_SQL), ['234', null], true]
                , ['LEFT: STRING, RIGHT: NULL, NONSQL', Sets.intersection(ACCEPT_STRINGS_LEFT, ACCEPT_NULLS_RIGHT_NONSQL), ['234', null], false]
                , ['LEFT: STRING, RIGHT: COLLECTION, SQL', Sets.intersection(ACCEPT_NULLS_LEFT, ACCEPT_COLLECTIONS_RIGHT_SQL), ['', ['a']], true]
                , ['LEFT: STRING, RIGHT: COLLECTION, NONSQL', Sets.intersection(ACCEPT_NULLS_LEFT, ACCEPT_COLLECTIONS_RIGHT_NON_SQL), ['фывапролджэ', [3, 4]], false]
                , ['LEFT: NULL, RIGHT: NULL, SQL', Sets.intersection(ACCEPT_NULLS_LEFT, ACCEPT_NULLS_RIGHT_SQL), [null, null], true]
                , ['LEFT: NULL, RIGHT: NULL, NONSQL', Sets.intersection(ACCEPT_NULLS_LEFT, ACCEPT_NULLS_RIGHT_NONSQL), [null, null], false]
                , ['LEFT: NULL, RIGHT: STRING, SQL', Sets.intersection(ACCEPT_NULLS_LEFT, ACCEPT_STRINGS_RIGHT), [null, ''], true]
                , ['LEFT: NULL, RIGHT: STRING, NONSQL', Sets.intersection(ACCEPT_NULLS_LEFT, ACCEPT_STRINGS_RIGHT), [null, ''], false]
                , ['LEFT: NULL, RIGHT: NUMBER, SQL', Sets.intersection(ACCEPT_NULLS_LEFT, ACCEPT_NUMBERS_RIGHT), [null, Long.MIN_VALUE], true]
                , ['LEFT: NULL, RIGHT: NUMBER, NONSQL', Sets.intersection(ACCEPT_NULLS_LEFT, ACCEPT_NUMBERS_RIGHT), [null, Long.MIN_VALUE], false]
                , ['LEFT: NULL, RIGHT: COLLECTION, SQL', Sets.intersection(ACCEPT_NULLS_LEFT, ACCEPT_COLLECTIONS_RIGHT_SQL), [null, ['a']], true]
                , ['LEFT: NULL, RIGHT: COLLECTION, NONSQL', Sets.intersection(ACCEPT_NULLS_LEFT, ACCEPT_COLLECTIONS_RIGHT_NON_SQL), [null, [3, 4]], false]
        ]
    }

    /** APPLY tests **/

    @Test(dataProvider = 'dpApplyOperandTypes')
    void conditionOp_apply_full_positive(String desc, Collection<ConditionOp> ops, List args, boolean sqlNullsRule) {
        asTest {
            assert desc
            ops.each { ConditionOp op ->
                def stepDesc = "${op}.apply(${args[0]} (${args[0]?.class}), ${args[1]} (${args[1]?.class}), $sqlNullsRule)"
                asStep(stepDesc) {
                    try {
                        def res = op.apply(args[0], args[1], sqlNullsRule)
                        logger.debug " $stepDesc = $res"
                    } catch (ClassCastException cce) {
                        logger.info("Exception caught: $cce", cce)
                        assert CLASS_CAST_OPS.contains(op) && (!(args[0].class.isAssignableFrom(args[1]?.class)))
                    } catch (Exception e) {
                        Assertions.weakAssertSilently("No exceptions expected but encountered one:$e", !e)
                    }
                }
            }
        }
    }


    @Test(dataProvider = 'dpApplyOperandTypes')
    void conditionOp_apply_full_negative(String desc, Collection<ConditionOp> ops, List args, boolean sqlNullsRule) {
        asTest {
            assert desc
            (ConditionOp.values() - ops).each { ConditionOp op ->
                def stepDesc = "${args[0]} (${args[0]?.class?.simpleName}) ${op} ${args[1]} (${args[1]?.class?.simpleName}); SQL Nulls rule: ${sqlNullsRule ? 'ON' : 'OFF'})"
                asStep(stepDesc) {
                    Exception ex = null
                    try {
                        def res = op.apply(args[0], args[1], sqlNullsRule)
                        logger.debug " $stepDesc = $res"
                    } catch (Exception e) {
                        ex = e
                    }
                    Assertions.weakAssertSilently "$ex is IllegalArgumentException", ex instanceof IllegalArgumentException
                }
            }
        }
    }

    @DataProvider
    Object[][] applyTestDp() {
        [
                /*  [true, ConditionOp.EQ, 3, 3, false]
                , [false, ConditionOp.EQ, 3, 4, false]
                , [true, ConditionOp.EQ, '23', '23', false]
                , [true, ConditionOp.EQ, null, null, false]

                , [false, ConditionOp.NEQ, 3, 3, true]
                , [true, ConditionOp.NEQ, 3, 4, false]
                , [true, ConditionOp.NEQ, 3, null, false]
                , [true, ConditionOp.NEQ, null, 3, false]
                , [false, ConditionOp.NEQ, null, 3, true]
                , [false, ConditionOp.NEQ, null, null, false]
                , [false, ConditionOp.NEQ, '23', '23', false]

                , [false, ConditionOp.GT, 3, 3, false]
                , [true, ConditionOp.GT, Long.MAX_VALUE, 99, false]
                , [false, ConditionOp.GT, '23', '43', true]
                , [true, ConditionOp.GT, '43', '243', false]

                , [false, ConditionOp.GTE, -5, 3, true]
                , [false, ConditionOp.GTE, -5, 3, false]
                , [true, ConditionOp.GTE, 3, 3, true]
                , [true, ConditionOp.GTE, Long.MAX_VALUE, 99, false]
                , [false, ConditionOp.GTE, '23', '43', false]
                , [true, ConditionOp.GTE, '43', '43', true]
                , [true, ConditionOp.GTE, '43', '243', false]

                , [true, ConditionOp.LTE, -5, 3, false]
                , [true, ConditionOp.LTE, 3, 3, false]
                , [false, ConditionOp.LTE, Long.MAX_VALUE, 99, false]
                , [true, ConditionOp.LTE, '23', '43', false]
                , [false, ConditionOp.LTE, '43', '243', false]

                , [true, ConditionOp.IN, '43', ['243', '43'], true]
                , [false, ConditionOp.IN, 1, [], true]     */

                  [true, ConditionOp.EQ, 3, 3, false]
                , [false, ConditionOp.EQ, 3, 5, false]
                , [true, ConditionOp.EQ, 3, 3, true]
                , [false, ConditionOp.EQ, 3, 5, true]
                , [false, ConditionOp.EQ, 3, '3', false]
                , [false, ConditionOp.EQ, 3, '3', true]
                , [false, ConditionOp.EQ, 3, null, false]
                , [false, ConditionOp.EQ, 3, null, false]
                , [false, ConditionOp.EQ, 3, [3], false]
                , [false, ConditionOp.EQ, '3', 3, false]
                , [false, ConditionOp.EQ, '3', 3, true]
                , [true, ConditionOp.EQ, 'qwer', 'qwer', false]
                , [false, ConditionOp.EQ, 'qwer', 'qww2', false]
                , [true, ConditionOp.EQ, 'qwer', 'qwer', true]
                , [false, ConditionOp.EQ, 'qwer', 'reqw', true]
                , [false, ConditionOp.EQ, 'qwer', null, false]
                , [false, ConditionOp.EQ, 'qwer', ['qwer'], false]
                , [false, ConditionOp.EQ, null, 3, false]
                , [false, ConditionOp.EQ, null, 3, true]
                , [false, ConditionOp.EQ, null, 'null', false]
                , [false, ConditionOp.EQ, null, 'null', true]
                , [true, ConditionOp.EQ, null, null, false]
                , [false, ConditionOp.EQ, null, ['3'], false]

                , [true, ConditionOp.NEQ, 3, 4, false]
                , [false, ConditionOp.NEQ, 3, 3, false]
                , [true, ConditionOp.NEQ, 3, 4, true]
                , [false, ConditionOp.NEQ, 3, 3, true]
                , [true, ConditionOp.NEQ, 3, '3', false]
                , [true, ConditionOp.NEQ, 3, '3', true]
                , [true, ConditionOp.NEQ, 3, null, false]
                , [true, ConditionOp.NEQ, 3, [3], false]
                , [true, ConditionOp.NEQ, '3', 3, false]
                , [true, ConditionOp.NEQ, '3', 3, true]
                , [true, ConditionOp.NEQ, 'qwer', 'reqw', false]
                , [false, ConditionOp.NEQ, 'qwer', 'qwer', false]
                , [true, ConditionOp.NEQ, 'qwer', 'reqw', true]
                , [false, ConditionOp.NEQ, 'qwer', 'qwer', true]
                , [true, ConditionOp.NEQ, 'qwer', null, false]
                , [true, ConditionOp.NEQ, 'qwer', ['qwer'], false]
                , [true, ConditionOp.NEQ, null, 3, false]
                , [false, ConditionOp.NEQ, null, 3, true]
                , [true, ConditionOp.NEQ, null, 'null', false]
                , [false, ConditionOp.NEQ, null, 'null', true]
                , [false, ConditionOp.NEQ, null, null, false]
                , [true, ConditionOp.NEQ, null, [null], false]

                , [true, ConditionOp.GT, 9, 3, false]
                , [false, ConditionOp.GT, 9, 15, false]
                , [false, ConditionOp.GT, 9, 9, false]
                , [true, ConditionOp.GT, 9, 3, true]
                , [false, ConditionOp.GT, 9, 15, true]
                , [false, ConditionOp.GT, 9, 9, true]
                , [true, ConditionOp.GT, 'stringz', 'stringa', false]
                , [false, ConditionOp.GT, 'stringa', 'strinz', false]
                , [false, ConditionOp.GT, 'string', 'string', false]
                , [true, ConditionOp.GT, 'stringz', 'stringa', true]
                , [false, ConditionOp.GT, 'stringa', 'strinz', true]
                , [false, ConditionOp.GT, 'string', 'string', true]
                , [false, ConditionOp.GT, null, 3, false]
                , [false, ConditionOp.GT, null, 15, false]
                , [false, ConditionOp.GT, null, 3, true]
                , [false, ConditionOp.GT, null, 15, true]
                , [false, ConditionOp.GT, null, 'string', false]
                , [false, ConditionOp.GT, null, 'string', false]
                , [false, ConditionOp.GT, null, 'string', true]
                , [false, ConditionOp.GT, null, 'string', true]
                , [false, ConditionOp.GT, null, [null, false], false]
                , [false, ConditionOp.GT, null, [null], false]

                , [false, ConditionOp.LT, 9, 3, false]
                , [true, ConditionOp.LT, 9, 15, false]
                , [false, ConditionOp.LT, 9, 9, false]
                , [false, ConditionOp.LT, 9, 3, true]
                , [true, ConditionOp.LT, 9, 15, true]
                , [false, ConditionOp.LT, 9, 9, true]
                , [false, ConditionOp.LT, 'stringz', 'stringa', false]
                , [true, ConditionOp.LT, 'stringa', 'strinz', false]
                , [false, ConditionOp.LT, 'string', 'string', false]
                , [false, ConditionOp.LT, 'stringz', 'stringa', true]
                , [true, ConditionOp.LT, 'stringa', 'strinz', true]
                , [false, ConditionOp.LT, 'string', 'string', true]
                , [true, ConditionOp.LT, null, 3, false]
                , [true, ConditionOp.LT, null, 15, false]
                , [false, ConditionOp.LT, null, 3, true]
                , [false, ConditionOp.LT, null, 15, true]
                , [true, ConditionOp.LT, null, 'string', false]
                , [true, ConditionOp.LT, null, 'string', false]
                , [false, ConditionOp.LT, null, 'string', true]
                , [false, ConditionOp.LT, null, 'string', true]
                , [true, ConditionOp.LT, null, [null, false], false]
                , [true, ConditionOp.LT, null, [null], false]

                , [true, ConditionOp.GTE, 9, 3, false]
                , [false, ConditionOp.GTE, 9, 15, false]
                , [true, ConditionOp.GTE, 9, 9, false]
                , [true, ConditionOp.GTE, 9, 3, true]
                , [false, ConditionOp.GTE, 9, 15, true]
                , [true, ConditionOp.GTE, 9, 9, true]
                , [true, ConditionOp.GTE, 'stringz', 'stringa', false]
                , [false, ConditionOp.GTE, 'stringa', 'strinz', false]
                , [true, ConditionOp.GTE, 'string', 'string', false]
                , [true, ConditionOp.GTE, 'stringz', 'stringa', true]
                , [false, ConditionOp.GTE, 'stringa', 'strinz', true]
                , [true, ConditionOp.GTE, 'string', 'string', true]
                , [false, ConditionOp.GTE, null, 3, false]
                , [false, ConditionOp.GTE, null, 15, false]
                , [false, ConditionOp.GTE, null, 3, true]
                , [false, ConditionOp.GTE, null, 15, true]
                , [false, ConditionOp.GTE, null, 'string', false]
                , [false, ConditionOp.GTE, null, 'string', false]
                , [false, ConditionOp.GTE, null, 'string', true]
                , [false, ConditionOp.GTE, null, 'string', true]
                , [false, ConditionOp.GTE, null, [null, false], false]
                , [false, ConditionOp.GTE, null, [null], false]

                , [false, ConditionOp.LTE, 9, 3, false]
                , [true, ConditionOp.LTE, 9, 15, false]
                , [true, ConditionOp.LTE, 9, 9, false]
                , [false, ConditionOp.LTE, 9, 3, true]
                , [true, ConditionOp.LTE, 9, 15, true]
                , [true, ConditionOp.LTE, 9, 9, true]
                , [false, ConditionOp.LTE, 'stringz', 'stringa', false]
                , [true, ConditionOp.LTE, 'stringa', 'strinz', false]
                , [true, ConditionOp.LTE, 'string', 'string', false]
                , [false, ConditionOp.LTE, 'stringz', 'stringa', true]
                , [true, ConditionOp.LTE, 'stringa', 'strinz', true]
                , [true, ConditionOp.LTE, 'string', 'string', true]
                , [true, ConditionOp.LTE, null, 3, false]
                , [true, ConditionOp.LTE, null, 15, false]
                , [false, ConditionOp.LTE, null, 3, true]
                , [false, ConditionOp.LTE, null, 15, true]
                , [true, ConditionOp.LTE, null, 'string', false]
                , [true, ConditionOp.LTE, null, 'string', false]
                , [false, ConditionOp.LTE, null, 'string', true]
                , [false, ConditionOp.LTE, null, 'string', true]
                , [true, ConditionOp.LTE, null, [null, false], false]
                , [true, ConditionOp.LTE, null, [null], false]


                , [true, ConditionOp.IN, 9, [3, 9, 5], false]
                , [false, ConditionOp.IN, 9, [15, 1, 5], false]
                , [true, ConditionOp.IN, 9, [3, 9, 0], true]
                , [false, ConditionOp.IN, 9, [15, 1, 4], true]
                , [true, ConditionOp.IN, 'string', [null, 1, 'string'], false]
                , [false, ConditionOp.IN, 'string', [null, 1], false]
                , [true, ConditionOp.IN, 'string', [null, 1, 'string'], true]
                , [false, ConditionOp.IN, 'string', [null, 1], true]
                , [true, ConditionOp.IN, null, [null, 6, 'q'], false]
                , [false, ConditionOp.IN, null, [6, 'q'], false]
/**/            , [false, ConditionOp.IN, null, [null], true]
                , [false, ConditionOp.IN, null, [5, 1, 3], true]

                , [false, ConditionOp.NOT_IN, 9, [3, 9, 5], false]
                , [true, ConditionOp.NOT_IN, 9, [15, 1, 5], false]
                , [false, ConditionOp.NOT_IN, 9, [3, 9, 0], true]
                , [true, ConditionOp.NOT_IN, 9, [15, 1, 4], true]
                , [false, ConditionOp.NOT_IN, 'string', [null, 1, 'string'], false]
                , [true, ConditionOp.NOT_IN, 'string', [null, 1], false]
                , [false, ConditionOp.NOT_IN, 'string', [null, 1, 'string'], true]
                , [true, ConditionOp.NOT_IN, 'string', [null, 1], true]
                , [false, ConditionOp.NOT_IN, null, [null, 6, 'q'], false]
                , [true, ConditionOp.NOT_IN, null, [6, 'q'], false]
/**/            , [false, ConditionOp.NOT_IN, null, [null], true]
/**/            , [false, ConditionOp.NOT_IN, null, [5, 1, 3], true]

                , [false, ConditionOp.IS_NULL, 9, 15, false]
                , [false, ConditionOp.IS_NULL, 9, 15, true]
                , [false, ConditionOp.IS_NULL, 9, '15', false]
                , [false, ConditionOp.IS_NULL, 9, '15', true]
                , [false, ConditionOp.IS_NULL, 9, null, false]
                , [false, ConditionOp.IS_NULL, 9, null, true]
                , [false, ConditionOp.IS_NULL, 9, [15], false]
                , [false, ConditionOp.IS_NULL, 'string', 15, false]
                , [false, ConditionOp.IS_NULL, 'string', 15, true]
                , [false, ConditionOp.IS_NULL, 'string', 'string', false]
                , [false, ConditionOp.IS_NULL, 'string', 'string', true]
                , [false, ConditionOp.IS_NULL, 'string', null, false]
                , [false, ConditionOp.IS_NULL, 'string', null, true]
                , [false, ConditionOp.IS_NULL, 'string', [null], false]
                , [true, ConditionOp.IS_NULL, null, 3, false]
                , [true, ConditionOp.IS_NULL, null, 3, true]
                , [true, ConditionOp.IS_NULL, null, 'string', false]
                , [true, ConditionOp.IS_NULL, null, 'string', true]
                , [true, ConditionOp.IS_NULL, null, null, false]
                , [true, ConditionOp.IS_NULL, null, null, true]
                , [true, ConditionOp.IS_NULL, null, [null], false]

                , [true, ConditionOp.IS_NOT_NULL, 9, 15, false]
                , [true, ConditionOp.IS_NOT_NULL, 9, 15, true]
                , [true, ConditionOp.IS_NOT_NULL, 9, '15', false]
                , [true, ConditionOp.IS_NOT_NULL, 9, '15', true]
                , [true, ConditionOp.IS_NOT_NULL, 9, null, false]
                , [true, ConditionOp.IS_NOT_NULL, 9, null, true]
                , [true, ConditionOp.IS_NOT_NULL, 9, [15], false]
                , [true, ConditionOp.IS_NOT_NULL, 'string', 15, false]
                , [true, ConditionOp.IS_NOT_NULL, 'string', 15, true]
                , [true, ConditionOp.IS_NOT_NULL, 'string', 'string', false]
                , [true, ConditionOp.IS_NOT_NULL, 'string', 'string', true]
                , [true, ConditionOp.IS_NOT_NULL, 'string', null, false]
                , [true, ConditionOp.IS_NOT_NULL, 'string', null, true]
                , [true, ConditionOp.IS_NOT_NULL, 'string', [null], false]
                , [false, ConditionOp.IS_NOT_NULL, null, 3, false]
                , [false, ConditionOp.IS_NOT_NULL, null, 3, true]
                , [false, ConditionOp.IS_NOT_NULL, null, 'string', false]
                , [false, ConditionOp.IS_NOT_NULL, null, 'string', true]
                , [false, ConditionOp.IS_NOT_NULL, null, null, false]
                , [false, ConditionOp.IS_NOT_NULL, null, null, true]
                , [false, ConditionOp.IS_NOT_NULL, null, [null], false]

                , [false, ConditionOp.LIKE, 'stringtxt', 'string.txt', false]
                , [true, ConditionOp.LIKE, 'string.TXT', 'string_txt', false]
                , [true, ConditionOp.LIKE, 'string.TXT', 'string_txt', true]
                , [false, ConditionOp.LIKE, 'stringTXT', 'string.txt', true]
                , [false, ConditionOp.LIKE, null, 'string', false]
                , [false, ConditionOp.LIKE, null, 'string', true]

                , [true, ConditionOp.NOT_LIKE, 'stringtxt', 'string.txt', false]
                , [false, ConditionOp.NOT_LIKE, 'string.TXT', 'string_txt', false]
                , [false, ConditionOp.NOT_LIKE, 'string.TXT', 'string_txt', true]
                , [true, ConditionOp.NOT_LIKE, 'stringTXT', 'string.txt', true]
                , [true, ConditionOp.NOT_LIKE, null, 'string', false]
/*todo check*/  , [false, ConditionOp.NOT_LIKE, null, 'string', true]

                , [true, ConditionOp.BTEQ, 1, 1, false]
                , [false, ConditionOp.BTEQ, 0, 1, false]
                , [true, ConditionOp.BTEQ, 1, 1, true]
                , [false, ConditionOp.BTEQ, 0, 1, true]
                , [false, ConditionOp.BTEQ, null, 1, false]
                , [false, ConditionOp.BTEQ, null, 1, true]


                , [true, ConditionOp.BTANY, 1, 1, false]
                , [true, ConditionOp.BTANY, 0, 1, false]
                , [false, ConditionOp.BTANY, 0, 0, false]
                , [true, ConditionOp.BTANY, 1, 1, true]
                , [true, ConditionOp.BTANY, 0, 1, true]
                , [false, ConditionOp.BTANY, null, 0, false]
                , [false, ConditionOp.BTANY, null, 0, true]
                , [true, ConditionOp.BTANY, null, 1, false]
                , [false, ConditionOp.BTANY, null, 1, true]



                , [false, ConditionOp.BTNEQ, 1, 1, false]
                , [true, ConditionOp.BTNEQ, 0, 1, false]
                , [false, ConditionOp.BTNEQ, 1, 1, true]
                , [true, ConditionOp.BTNEQ, 0, 1, true]
                , [true, ConditionOp.BTNEQ, null, 1, false]
/*todo check*/  , [false, ConditionOp.BTNEQ, null, 1, true]
        ]

    }

    @Test(dataProvider = 'applyTestDp')
    void parametrized_ConditionOp_apply_test(boolean expectedRes, ConditionOp op, def left, def right, @Optional() Boolean sqlNulls) {
        assert op.apply(left, right, sqlNulls as boolean) == expectedRes
    }

//
//    @Test
//    void test()
//    {
//
//        println
//    }

}
